{% extends "layout.html" %}

<!-- Home page for testing Rhasspy services -->

{% block body %}

<!-- siteId -->
<h3 class="text-center" title="Hermes Site Id" x-text="getSiteId()"></h3>

<!-- Services Bar -->
<div id="services" class="btn-group text-center w-100">

    <a href="{{ url_prefix }}/settings#mqtt" class="btn flex-fill p-2"
	   x-bind:title="'MQTT: ' + (profile.mqtt.enabled ? 'external' : 'internal')"
	   x-bind:class="{ 'btn-dark': !profile.mqtt.enabled, 'btn-success' : profile.mqtt.enabled }">
	    <i class="fas fa-inverse fa-network-wired fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not mqtt_external %}
            Internal MQTT
            {% else %}
            External MQTT
            {% endif %}
        </span>
    </a>

    <a href="{{ url_prefix }}/settings#microphone" class="btn flex-fill p-2"
	   x-bind:title="'Audio input: ' + profile.microphone.system"
	   x-bind:class="{ 'btn-dark': profile.microphone.system === 'dummy', 'btn-success': profile.microphone.system !== 'dummy' }">
      <i class="fas fa-inverse fa-microphone fa-lg"></i>
      <br>
      <span class="service-label">
          {% if not has_microphone %}
          Microphone
          {% else %}
          {{ profile.get("microphone.system") }}
          {% endif %}
      </span>
    </a>

    <a href="{{ url_prefix }}/settings#wake" class="btn flex-fill p-2"
       x-bind:title="'Wake word: ' + profile.wake.system"
       x-bind:class="{ 'btn-dark': profile.wake.system === 'dummy', 'btn-success': profile.wake.system !== 'dummy' }">
        <i class="fas fa-inverse fa-exclamation-circle fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_wake %}
            Wake
            {% else %}
            {{ profile.get("wake.system") }}
            {% endif %}
        </span>
    </a>

    <a href="{{ url_prefix }}/settings#speech" class="btn flex-fill p-2"
       x-bind:title="'Speech to text: ' + profile.speech_to_text.system"
       x-bind:class="{ 'btn-dark': profile.speech_to_text.system === 'dummy', 'btn-success': profile.speech_to_text.system !== 'dummy' }">
        <i class="fas fa-inverse fa-phone-volume fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_speech_to_text %}
            Speech to Text
            {% else %}
            {{ profile.get("speech_to_text.system") }}
            {% endif %}
        </span>
    </a>

    <a href="{{ url_prefix }}/settings#intent" class="btn flex-fill p-2"
       x-bind:title="'Intent recognition: ' + profile.intent.system"
       x-bind:class="{ 'btn-dark': profile.intent.system === 'dummy', 'btn-success': profile.intent.system !== 'dummy' }">
        <i class="fas fa-inverse fa-comment fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_intent %}
            Intent Recognition
            {% else %}
            {{ profile.get("intent.system") }}
            {% endif %}
        </span>
	  </a>

    <a href="{{ url_prefix }}/settings#tts" class="btn flex-fill p-2"
       x-bind:title="'Text to speech: ' + profile.text_to_speech.system"
       x-bind:class="{ 'btn-dark': profile.text_to_speech.system === 'dummy', 'btn-success': profile.text_to_speech.system !== 'dummy' }">
        <i class="fas fa-inverse fa-paper-plane fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_text_to_speech %}
            Text to Speech
            {% else %}
            {{ profile.get("text_to_speech.system") }}
            {% endif %}
        </span>
	  </a>

    <a href="{{ url_prefix }}/settings#sounds" class="btn flex-fill p-2"
       x-bind:title="'Audio output: ' + profile.sounds.system"
       x-bind:class="{ 'btn-dark': profile.sounds.system === 'dummy', 'btn-success': profile.sounds.system !== 'dummy' }">
        <i class="fas fa-inverse fa-volume-up fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_sounds %}
            Sounds
            {% else %}
            {{ profile.get("sounds.system") }}
            {% endif %}
        </span>
	  </a>

    <a href="{{ url_prefix }}/settings#handle" class="btn flex-fill p-2"
       x-bind:title="'Intent handling: ' + profile.handle.system"
       x-bind:class="{ 'btn-dark': profile.handle.system === 'dummy', 'btn-success': profile.handle.system !== 'dummy'}">
        <i class="fas fa-inverse fa-bolt fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_handle %}
            Intent Handling
            {% else %}
            {{ profile.get("handle.system") }}
            {% endif %}
        </span>
	  </a>

    <a href="{{ url_prefix }}/settings#dialogue" class="btn flex-fill p-2"
       x-bind:title="'Dialogue management: ' + profile.dialogue.system"
       x-bind:class="{ 'btn-dark': profile.dialogue.system === 'dummy', 'btn-success': profile.dialogue.system !== 'dummy' }">
        <i class="fas fa-inverse fa-tasks fa-lg"></i>
        <br>
        <span class="service-label">
            {% if not has_dialogue %}
            Dialogue
            {% else %}
            {{ profile.get("dialogue.system") }}
            {% endif %}
        </span>
	  </a>

</div>
<!-- End Services Bar -->

<!-- Microphone/STT Testing -->
<div class="card-group mt-2">
    <div class="card test-card">
        <div class="card-body">
            <div class="container">
                <div class="row">
                    <div class="col">
                        <button id="wakeup" class="btn btn-warning" onclick="wakeUp()" title="Wake up Rhasspy and listen for a voice command" {% if not (has_speech_to_text and has_intent) %}disabled {% endif %}>
                            <i class="fas fa-2x fa-exclamation-circle"></i>
                        </button>
                        <span>Wake Up</span>
                        {% if not (has_speech_to_text and has_intent) %}
                        <br>
                        <span class="text-muted">(need <a href="settings#speech">speech to text</a> and <a href="settings#intent">intent</a> systems)</span>
                        {% endif %}
                    </div>
                    <div class="col">
                        <div class="btn-group w-100">
                            <button id="play-command" onclick="playCommand()" class="btn btn-success" title="Play the last recorded voice command" {% if not has_sounds %}disabled{% endif %}>
                                <i class="fas fa-2x fa-play"></i>
                            </button>
                            <button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split w-25" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" {% if not has_sounds %}disabled{% endif %}>
                                <span class="sr-only">Toggle Dropdown</span>
                            </button>
                            <div class="dropdown-menu">
                                <a class="dropdown-item" href="{{ url_prefix }}/api/play-recording">
                                    <i class="fas fa-download"></i>
                                    Download WAV
                                </a>
                            </div>
                        </div>

                        <span>Play Recording</span>
                        {% if not has_sounds %}
                        <br>
                        <span class="text-muted">(no <a href="settings#sounds">sound</a> system)</span>
                        {% endif %}
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="card test-card">
        <div class="card-body">
            <input id="wav-file" type="file" onchange="uploadWAV()" hidden>
            <button id="upload" onclick="chooseWAV()" class="btn btn-info" title="Upload WAV voice command and recognize it" {% if not has_speech_to_text %}disabled{% endif %}>
                <i class="fas fa-2x fa-upload"></i>
            </button>
            <span>Upload WAV File</span>
            {% if not has_speech_to_text %}
            <br>
            <span class="text-muted">(no <a href="settings#speech">speech to text</a> system)</span>
            {% endif %}
        </div>
    </div>
</div>
<!-- End Microphone/STT Testing -->

<!-- Intent Recognition Testing -->
<div class="container-fluid mt-3">
    <form onsubmit="recognize()">
        <div class="row">
            <div class="col-xs-auto">
                <button type="submit" id="intent-recognize" title="Recognize an intent from text" class="btn btn-primary" {% if not has_intent %}disabled{% endif %}>
                    <i class="fas fa-inverse fa-comment"></i>
                    Recognize
                </button>
            </div>

            {% if not has_intent %}
            <div class="col-auto">
                <span class="text-muted">(no <a href="settings#intent">intent</a> system)</span>
            </div>
            {% endif %}

            <div class="col">
                <input type="text" id="intent-text" class="form-control ml-1" placeholder="Text to recognize" {% if not has_intent %}readonly{% endif %}>
            </div>
            <div class="col-xs-auto">
                <input type="checkbox" class="mr-2" id="handle-intent" {% if not has_intent %}disabled{% endif %}>
                <label for="handle-intent" class="col-form-label" title="Send recognized intent to intent handler">Handle <i class="fas fa-bolt ml-1"></i> </label>
            </div>
        </div>
        <div class="row">
            <div class="col">
                <div id="intent-error" class="col alert alert-danger mt-3 mb-0" style="display: none;">
                    No intent recognized
                </div>
                <div id="intent-summary" style="display:none;" class="form-group mt-3 mb-0">
                    <div class="form-row">
                        <div id="intent-name" title="Intent name" class="badge badge-danger"></div>
                    </div>
                    <div class="form-row">
                        <ul id="intent-slots" title="Intent slots" class="mt-1"></ul>
                    </div>
                    <div class="form-row">
                        <button type="button" title="Show intent JSON" onclick="$('#intentJSONModal').modal('show')" class="btn btn-secondary">Show JSON</button>
                    </div>
                </div>
            </div>
        </div>
    </form>
    <form onsubmit="speak()" class="mt-3">
        <div class="row">
            <div class="col-xs-auto">
                <button type="submit" id="tts-speak" title="Speak a sentence using text to speech" class="btn btn-info" {% if not has_text_to_speech %}disabled{% endif %}>
                    <i class="fas fa-inverse fa-paper-plane"></i>
                    Speak
                </button>
            </div>
            {% if not has_text_to_speech %}
            <div class="col-auto">
                <span class="text-muted">(no <a href="settings#tts">text to speech</a> system)</span>
            </div>
            {% endif %}
            <div class="col">
                <input type="text" id="tts-text" class="form-control ml-1" placeholder="Text to speak" {% if not has_text_to_speech %}readonly{% endif %}>
            </div>
        </div>
    </form>
    <form onsubmit="setVolume()" class="mt-3">
        <div class="row">
            <div class="col-xs-auto">
                <button type="submit" id="set-volume" title="Set the volume for multiple sites" class="btn btn-success">
                    <i class="fas fa-inverse fa-volume-up"></i>
                    Set Volume
                </button>
            </div>
            <div class="col-auto">
                <input type="number" id="volume-value" class="form-control" min="0" max="1" step="0.05" value="1">
            </div>
            <div class="col">
                <input type="text" id="volume-sites" class="form-control" placeholder="site1,site2">
            </div>
        </div>
    </form>
</div>
<!-- End Intent Recognition Testing -->

<!-- Intent JSON Modal -->
<div id="intentJSONModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="intentJSONModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="intentJSONModalLabel">Intent JSON</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <textarea id="intent-json" type="text" class="form-control code" rows="15"></textarea>
            </div>
        </div>
    </div>
</div>
<!-- End Intent JSON Modal -->

{% endblock %}

{% block script %}
<script type="text/javascript">

 function getSiteId() {
     var siteIdStr = rhasspy.profile.mqtt.site_id || 'default';
     return siteIdStr.split(',')[0]
 }

 // Show intent and slots in web UI
 function setIntent(response) {
     $('#intent-error').hide()
     $('#intent-summary').hide()
     $('#intent-slots li').remove()

     $('#intent-json').val(JSON.stringify(response, null, 4));
     $('#intent-text').val(response.raw_text || response.text);

     if (response.intent.name.length == 0) {
         $('#intent-error').show()
         return;
     }

     $('#intent-summary').show()
     $('#intent-name').text(response.intent.name)
     for (slotName in response.slots) {
         $('#intent-slots').append(
             '<li>' +
             '<span>' + response.slots[slotName] + '</span>' +
             '<span class="badge badge-primary ml-1">' + slotName + '</span>' +
             '</li>'
         );
     }
 }

 // Wake Rhasspy up, listen for a voice command, then recognize the intent.
 function wakeUp() {
     $('#wakeup').prop('disabled', true);
     rhasspy.postBusy('Listening for command', '/api/listen-for-command')
            .always(function() {
                $('#wakeup').prop('disabled', false);
            })
            .done(function(response) {
                $('#intent-text').val(response['raw_text']);
                setIntent(response);
            });
 }

 // POST to /api/play-recording to play last recorded voice command
 function playCommand() {
     $('#play-command').prop('disabled', true);
     rhasspy.postBusy('Playing last command', '/api/play-recording')
            .always(function() {
                $('#play-command').prop('disabled', false);
            });
 }

 // Click hidden file input for WAV upload
 function chooseWAV() {
     event.preventDefault();
     $('#wav-file').click();
     return false;
 }

 // Read WAV file into a buffer and POST to /api/speech-to-intent
 function uploadWAV() {
     var file = event.target.files[0];

     var reader = new FileReader();
     reader.onload = function() {
         var wavData = this.result;
         rhasspy.postBusy('Transcribing WAV',
                          '/api/speech-to-intent',
                          wavData, true, 'audio/wav')
                .done(function(response) {
                    setIntent(response);
                });
     }

     reader.readAsArrayBuffer(file);
 }

 // POST text to /api/text-to-intent and display intent
 function recognize() {
     event.preventDefault();

     var text = $('#intent-text').val();
     if (text.length > 0) {
         $('#intent-recognize').prop('disabled', true);
         params = '?nohass=true'
         if ($('#handle-intent').prop('checked')) {
             params = ''
         }

         rhasspy.postBusy('Recognizing intent', '/api/text-to-intent' + params, text)
                .always(function() {
                    $('#intent-recognize').prop('disabled', false);
                })
                .done(function(response) {
                    setIntent(response);
                });
     } else {
         alert('No text to recognize')
     }

     return false;
 }

 // POST text to /api/text-to-speech to speak sentence
 function speak() {
     event.preventDefault();

     var text = $('#tts-text').val();
     if (text.length > 0) {
         $('#tts-speak').prop('disabled', true);
         rhasspy.postBusy(text, '/api/text-to-speech', text)
                .always(function() {
                    $('#tts-speak').prop('disabled', false);
                });
     } else {
         alert('No text to speak')
     }

     return false;
 }

 // POST volume and site ids to /api/set-volume
 function setVolume() {
     event.preventDefault();

     var volume = $('#volume-value').val();
     var siteIds = $('#volume-sites').val();

     $('#set-volume').prop('disabled', true);
     rhasspy.postBusy('Setting volume', '/api/set-volume?siteId=' + siteIds, volume)
            .always(function() {
                $('#set-volume').prop('disabled', false);
            });

     return false;
 }

 $(document).ready(() => {
     rhasspy.makeWebSocket(
         '/api/events/intent',
         (socket) => {
             socket.onmessage = (e) => {
                 setIntent(JSON.parse(e.data));
             }
         });
 })

</script>
{% endblock %}
